// 我们先来介绍特定函数模板定义
// 假如我们定义了一下这种结构,希望通过模板来完成下面的交换
struct job
{
    char name[40];
    double salary;
    int floor;
};

// 显式实例化
template <typename T>
void Swap(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
}

// 显式定义的方式 (使用 template<> 开头)
// 显式具体化也是基于函数模板的，只不过在函数模板的基础上，添加一个专门针对特定类型的、实现方式不同的具体化函数
// 上面的两个声明缺一不可,一个是通用函数模板,一个是job结构体定义,也就是说上面的两个定义是显式具体化的基础,显式具体化是上面两个实现的特例
template <>
void Swap<job>(job &j1, job &j2)
{
    double temp;
    temp = j1.salary;
    j1.salary = j2.salary;
    j2.salary = temp;
}

// 下面是按照优先级进行排序的(最匹配)
// 1. 没有函数模板优先级最高
void Swap(job &, job &);
// 2.具体化的函数模板,因为制定了类型
template <>
void Swap<job>(job &, job &);
// 3.通用函数模板
template <typename T>
void Swap(T &, T &);

// 由于编译器在重载解析时，会选择最匹配函数定义，所以在调用swap(job A, job B) 时，编译器会选择void swap(job &a, job &b) 函数定义，而屏蔽了模板函数

// 显式实例化和显式具体化

// 在代码中包含模板本身不会生成钢模板定义,它只是一个用于生成函数定义的方案。
// 编译器使用模板为特定类型生成函数定义时得到的是模板实例

// 也就是说 template <> void Swap<job>(job &j1, job &j2) 不会产生函数定义或者说函数声明
// 模板不是函数定义,但是使用具体东西(比如通过模板生成的函数)产生的"实例"是函数定义

// 因为函数调用提供的int参数类型产生的实例,这种实例化的方式称为隐式实例化

// C++还有一种方式叫做显式实例化. 意味着可以直接通过代码命令编译器生成函数定义

// 建立一个函数模板,下面的实例化将会依照这个模板创建一个函数声明(实例)
template <typename T>
void Swap(int i, int j)
{
    int temp;
    temp = i;
    i = j;
    j = temp;
}

// 下面的一行叫做显式实例化,我理解为 使用上面的swap()模板,生成一个使用int类型的实例
template void Swap<int>(int, int); // 创建一个特定的实例

// 下面这个叫做显式具体化,与显式实例化的区别是 template后面后没有 "<>" ,显式实例化没有<>, 显式具体化有<>
// template <> void Swap<int>(int &,int &);
// template <> void Swap(int &,int &);          // <int>可以省略
// 显式具体化理解为 不要使用Swap()模板生成函数定义,而应该使用专门为int类型显式地定义的函数定义
